/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package uk.ac.liv;

import java.awt.Cursor;
import java.awt.Dimension;
import java.awt.Toolkit;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.DefaultListModel;
import javax.swing.JFileChooser;
import javax.swing.JOptionPane;
import javax.swing.ListModel;
import javax.swing.SwingWorker;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.filechooser.FileNameExtensionFilter;
import org.apache.commons.lang.ArrayUtils;

/**
 *
 * @author Da Qi
 */
public class MainView extends javax.swing.JFrame {

    private ArrayList<Integer> selectedModIndex = new ArrayList();
    private static File currentDirectory;
    private static String plgsFile;
    private static String fastaFile;
    private static String mgfFile;
    private static String outputFile;
    private static Double xlMassShift;
    private static String xlResidue;                                       //Residue on which crosslinks occur
    private int missedCleaves;
    private int minPeptideLength;
    private HashMap<String, Double> fMods;
    private HashMap<String, Double> vMods;
    private Double ppmTol;                                          //Tolerance for the crosslink match    
    //*****************************************************************************
    //********** These are fixed parameters but could be added to the constructor **************
    private Boolean noCrosslinksOnCterminus = true;
    private Boolean noCrosslinksOnModifiedResidues = true;
    // modifications
    private HashMap<String, ModificationElement> fixedMods;
    private HashMap<String, ModificationElement> varMods;
    //
    private long runStartTime = -11;
    private long runStopTime = -11;
    //
    private SwingWorker sw;

    /**
     * Creates new form MainView
     */
    public MainView() {

        //... Setting standard look and feel ...//
        try {
            UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
        }
        catch (ClassNotFoundException ex) {
            System.out.println(ex.getStackTrace());
        }
        catch (InstantiationException ex) {
            System.out.println(ex.getStackTrace());
        }
        catch (IllegalAccessException ex) {
            System.out.println(ex.getStackTrace());
        }
        catch (UnsupportedLookAndFeelException ex) {
            System.out.println(ex.getStackTrace());
        }

        // Get the size of the screen
        Dimension dim = Toolkit.getDefaultToolkit().getScreenSize();

        // Determine the new location of the window
        int w = this.getSize().width;
        int h = this.getSize().height;
        int x = (dim.width - w) / 2;
        int y = (dim.height - h) / 2;

        // Move the window
        this.setLocation(x, y);

        initComponents();
    }

    /**
     * This method is called from within the constructor to initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is always
     * regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        jPanel1 = new javax.swing.JPanel();
        jPanel2 = new javax.swing.JPanel();
        jPanel3 = new javax.swing.JPanel();
        jLabel3 = new javax.swing.JLabel();
        jLabel4 = new javax.swing.JLabel();
        jScrollPane3 = new javax.swing.JScrollPane();
        jListVarMods = new javax.swing.JList();
        rmVarMod = new javax.swing.JButton();
        adVarMod = new javax.swing.JButton();
        jScrollPane4 = new javax.swing.JScrollPane();
        jListMods = new javax.swing.JList();
        jScrollPane2 = new javax.swing.JScrollPane();
        jListFixedMods = new javax.swing.JList();
        rmFixedMod = new javax.swing.JButton();
        adFixedMod = new javax.swing.JButton();
        jPanel4 = new javax.swing.JPanel();
        jspMissedCleaves = new javax.swing.JSpinner();
        jspPpmTol = new javax.swing.JSpinner();
        jspMinPepLen = new javax.swing.JSpinner();
        jLabel1 = new javax.swing.JLabel();
        jLabel2 = new javax.swing.JLabel();
        jLabel5 = new javax.swing.JLabel();
        jPanel6 = new javax.swing.JPanel();
        jcbNoCrosslinksOnCterminus = new javax.swing.JCheckBox();
        jcbNoCrosslinksOnModifiedResidues = new javax.swing.JCheckBox();
        jcbXlResidue = new javax.swing.JComboBox();
        jLabel8 = new javax.swing.JLabel();
        jspXlMassShift = new javax.swing.JSpinner();
        jLabel9 = new javax.swing.JLabel();
        jButton1 = new javax.swing.JButton();
        jbRun = new javax.swing.JButton();
        progressBar = new javax.swing.JProgressBar();
        jPanel5 = new javax.swing.JPanel();
        jLabel6 = new javax.swing.JLabel();
        jLabel7 = new javax.swing.JLabel();
        jtfFastaFile = new javax.swing.JTextField();
        jtfPlgsFile = new javax.swing.JTextField();
        jMenuBar1 = new javax.swing.JMenuBar();
        jMenu1 = new javax.swing.JMenu();
        jmiSelectFasta = new javax.swing.JMenuItem();
        jMenuSelectPlgs = new javax.swing.JMenuItem();
        jMenu2 = new javax.swing.JMenu();

        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
        setTitle("Crosslink Analysis");
        setResizable(false);

        jPanel1.setPreferredSize(new java.awt.Dimension(659, 400));

        jPanel2.setBorder(javax.swing.BorderFactory.createTitledBorder("Settings"));

        jPanel3.setBorder(javax.swing.BorderFactory.createEtchedBorder());

        jLabel3.setText("Fixed modifications:");

        jLabel4.setText("Variable modifications:");

        jListVarMods.setModel(new javax.swing.AbstractListModel() {
            String[] strings = { "--- none selected ---" };
            public int getSize() { return strings.length; }
            public Object getElementAt(int i) { return strings[i]; }
        });
        jScrollPane3.setViewportView(jListVarMods);

        rmVarMod.setText(">");
        rmVarMod.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                rmVarModActionPerformed(evt);
            }
        });

        adVarMod.setText("<");
        adVarMod.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                adVarModActionPerformed(evt);
            }
        });

        jListMods.setModel(new javax.swing.AbstractListModel() {
            String[] strings = { "Acetyl (K)", "Acetyl (N-term)", "Acetyl (Protein N-term)", "Amidated (C-term)", "Amidated (Protein C-term)", "Biotin (K)", "Biotin (N-term)", "Carbamidomethyl (C)", "Carbamyl (K)", "Carbamyl (N-term)", "Carboxymethyl (C)", "Cation:Na (C-term)", "Cation:Na (DE)", "cysTMT6plex (C)", "Deamidated (NQ)", "Dehydro (C)", "DiLeu4plex (K)", "DiLeu4plex (N-term)", "DiLeu4plex (Y)", "Dioxidation (M)", "Ethanolyl (C)", "ExacTagAmine (K)", "ExacTagThiol (C)", "Formyl (N-term)", "Formyl (Protein N-term)", "Guanidinyl (K)", "ICAT-C (C)", "ICAT-C:13C(9) (C)", "ICPL (K)", "ICPL (Protein N-term)", "ICPL:13C(6) (K)", "ICPL:13C(6) (Protein N-term)", "ICPL:13C(6)2H(4) (K)", "ICPL:13C(6)2H(4) (N-term)", "ICPL:13C(6)2H(4) (Protein N-term)", "ICPL:2H(4) (K)", "ICPL:2H(4) (Protein N-term)", "iTRAQ4plex (K)", "iTRAQ4plex (N-term)", "iTRAQ4plex (Y)", "iTRAQ8plex (K)", "iTRAQ8plex (N-term)", "iTRAQ8plex (Y)", "Label:18O(1) (C-term)", "Label:18O(2) (C-term)", "Methyl (C-term)", "Methyl (DE)", "Methylthio (C)", "mTRAQ (K)", "mTRAQ (N-term)", "mTRAQ (Y)", "mTRAQ:13C(3)15N(1) (K)", "mTRAQ:13C(3)15N(1) (N-term)", "mTRAQ:13C(3)15N(1) (Y)", "mTRAQ:13C(6)15N(2) (K)", "mTRAQ:13C(6)15N(2) (N-term)", "mTRAQ:13C(6)15N(2) (Y)", "NIPCAM (C)", "Oxidation (HW)", "Oxidation (M)", "Phospho (ST)", "Phospho (Y)", "Propionamide (C)", "Pyridylethyl (C)", "Sulfo (STY)", "TMT2plex (K)", "TMT2plex (N-term)", "TMT6plex (K)", "TMT6plex (N-term)" };
            public int getSize() { return strings.length; }
            public Object getElementAt(int i) { return strings[i]; }
        });
        jScrollPane4.setViewportView(jListMods);

        jListFixedMods.setModel(new javax.swing.AbstractListModel() {
            String[] strings = { "--- none selected ---" };
            public int getSize() { return strings.length; }
            public Object getElementAt(int i) { return strings[i]; }
        });
        jScrollPane2.setViewportView(jListFixedMods);

        rmFixedMod.setText(">");
        rmFixedMod.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                rmFixedModActionPerformed(evt);
            }
        });

        adFixedMod.setText("<");
        adFixedMod.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                adFixedModActionPerformed(evt);
            }
        });

        javax.swing.GroupLayout jPanel3Layout = new javax.swing.GroupLayout(jPanel3);
        jPanel3.setLayout(jPanel3Layout);
        jPanel3Layout.setHorizontalGroup(
            jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanel3Layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
                    .addComponent(jLabel3, javax.swing.GroupLayout.PREFERRED_SIZE, 107, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(jLabel4))
                .addGap(18, 18, 18)
                .addGroup(jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(jScrollPane2)
                    .addComponent(jScrollPane3))
                .addGap(18, 18, 18)
                .addGroup(jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(rmFixedMod)
                    .addComponent(adFixedMod)
                    .addComponent(rmVarMod)
                    .addComponent(adVarMod))
                .addGap(18, 18, 18)
                .addComponent(jScrollPane4, javax.swing.GroupLayout.PREFERRED_SIZE, 200, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addGap(14, 14, 14))
        );
        jPanel3Layout.setVerticalGroup(
            jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanel3Layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addGroup(jPanel3Layout.createSequentialGroup()
                        .addComponent(rmFixedMod)
                        .addGap(18, 18, 18)
                        .addComponent(adFixedMod)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 65, Short.MAX_VALUE)
                        .addGroup(jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                            .addComponent(jLabel4)
                            .addComponent(jScrollPane3, javax.swing.GroupLayout.PREFERRED_SIZE, 105, javax.swing.GroupLayout.PREFERRED_SIZE)
                            .addGroup(jPanel3Layout.createSequentialGroup()
                                .addComponent(rmVarMod)
                                .addGap(18, 18, 18)
                                .addComponent(adVarMod))))
                    .addComponent(jScrollPane4, javax.swing.GroupLayout.Alignment.TRAILING)
                    .addGroup(jPanel3Layout.createSequentialGroup()
                        .addGroup(jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                            .addComponent(jLabel3)
                            .addComponent(jScrollPane2, javax.swing.GroupLayout.PREFERRED_SIZE, 105, javax.swing.GroupLayout.PREFERRED_SIZE))
                        .addGap(0, 0, Short.MAX_VALUE)))
                .addContainerGap())
        );

        jspMissedCleaves.setModel(new javax.swing.SpinnerNumberModel());

        jspPpmTol.setModel(new javax.swing.SpinnerNumberModel(Double.valueOf(10.0d), Double.valueOf(0.0d), null, Double.valueOf(1.0d)));

        jspMinPepLen.setModel(new javax.swing.SpinnerNumberModel(Integer.valueOf(5), null, null, Integer.valueOf(1)));

        jLabel1.setText("Allowed max miss cleavage:");

        jLabel2.setText("MS1 tolerance window (ppm):");

        jLabel5.setText("Minimum peptide length:");

        javax.swing.GroupLayout jPanel4Layout = new javax.swing.GroupLayout(jPanel4);
        jPanel4.setLayout(jPanel4Layout);
        jPanel4Layout.setHorizontalGroup(
            jPanel4Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanel4Layout.createSequentialGroup()
                .addContainerGap()
                .addComponent(jLabel1)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                .addComponent(jspMissedCleaves, javax.swing.GroupLayout.PREFERRED_SIZE, 50, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addGap(18, 18, 18)
                .addComponent(jLabel2)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                .addComponent(jspPpmTol, javax.swing.GroupLayout.PREFERRED_SIZE, 50, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addGap(18, 18, 18)
                .addComponent(jLabel5)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                .addComponent(jspMinPepLen, javax.swing.GroupLayout.PREFERRED_SIZE, 50, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
        );
        jPanel4Layout.setVerticalGroup(
            jPanel4Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanel4Layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(jPanel4Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(jspMissedCleaves, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(jspPpmTol, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(jspMinPepLen, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(jLabel1)
                    .addComponent(jLabel2)
                    .addComponent(jLabel5))
                .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
        );

        jcbNoCrosslinksOnCterminus.setSelected(true);
        jcbNoCrosslinksOnCterminus.setText("No Crosslinks on C-terminus");

        jcbNoCrosslinksOnModifiedResidues.setSelected(true);
        jcbNoCrosslinksOnModifiedResidues.setText("No Crosslinks on Modified Residues");

        jcbXlResidue.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "A", "R", "N", "D", "C", "E", "Q", "G", "H", "I", "L", "K", "M", "F", "P", "S", "T", "W", "Y", "V" }));

        jLabel8.setText("Crosslink residue: ");

        jspXlMassShift.setModel(new javax.swing.SpinnerNumberModel(Double.valueOf(0.0d), null, null, Double.valueOf(1.0d)));

        jLabel9.setText("Crosslink mass: ");

        javax.swing.GroupLayout jPanel6Layout = new javax.swing.GroupLayout(jPanel6);
        jPanel6.setLayout(jPanel6Layout);
        jPanel6Layout.setHorizontalGroup(
            jPanel6Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanel6Layout.createSequentialGroup()
                .addContainerGap()
                .addComponent(jcbNoCrosslinksOnCterminus)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(jcbNoCrosslinksOnModifiedResidues)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(jLabel9)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(jspXlMassShift)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                .addComponent(jLabel8)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(jcbXlResidue, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addContainerGap())
        );
        jPanel6Layout.setVerticalGroup(
            jPanel6Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanel6Layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(jPanel6Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(jcbXlResidue, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(jLabel8)
                    .addComponent(jcbNoCrosslinksOnModifiedResidues)
                    .addComponent(jcbNoCrosslinksOnCterminus)
                    .addComponent(jspXlMassShift, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(jLabel9))
                .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
        );

        javax.swing.GroupLayout jPanel2Layout = new javax.swing.GroupLayout(jPanel2);
        jPanel2.setLayout(jPanel2Layout);
        jPanel2Layout.setHorizontalGroup(
            jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanel2Layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(jPanel3, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                    .addComponent(jPanel4, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                    .addComponent(jPanel6, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
                .addContainerGap())
        );
        jPanel2Layout.setVerticalGroup(
            jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanel2Layout.createSequentialGroup()
                .addComponent(jPanel3, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(jPanel4, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(jPanel6, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
        );

        jButton1.setText("Default");

        jbRun.setText("Run...");
        jbRun.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jbRunActionPerformed(evt);
            }
        });

        javax.swing.GroupLayout jPanel1Layout = new javax.swing.GroupLayout(jPanel1);
        jPanel1.setLayout(jPanel1Layout);
        jPanel1Layout.setHorizontalGroup(
            jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addComponent(jPanel2, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
            .addGroup(jPanel1Layout.createSequentialGroup()
                .addContainerGap()
                .addComponent(jButton1)
                .addGap(18, 18, 18)
                .addComponent(jbRun)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                .addComponent(progressBar, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                .addContainerGap())
        );
        jPanel1Layout.setVerticalGroup(
            jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanel1Layout.createSequentialGroup()
                .addComponent(jPanel2, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addGap(18, 18, 18)
                .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                        .addComponent(jButton1)
                        .addComponent(jbRun))
                    .addComponent(progressBar, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.PREFERRED_SIZE, 23, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addContainerGap(38, Short.MAX_VALUE))
        );

        jLabel6.setText("FastaFile: ");

        jLabel7.setText("Plgs File:");

        jtfFastaFile.setEditable(false);

        jtfPlgsFile.setEditable(false);

        javax.swing.GroupLayout jPanel5Layout = new javax.swing.GroupLayout(jPanel5);
        jPanel5.setLayout(jPanel5Layout);
        jPanel5Layout.setHorizontalGroup(
            jPanel5Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanel5Layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(jPanel5Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
                    .addComponent(jLabel6, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                    .addComponent(jLabel7, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addGroup(jPanel5Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(jtfFastaFile)
                    .addComponent(jtfPlgsFile))
                .addContainerGap())
        );
        jPanel5Layout.setVerticalGroup(
            jPanel5Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanel5Layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(jPanel5Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(jLabel6)
                    .addComponent(jtfFastaFile, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                .addGroup(jPanel5Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(jLabel7)
                    .addComponent(jtfPlgsFile, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addContainerGap(19, Short.MAX_VALUE))
        );

        jMenu1.setText("File");

        jmiSelectFasta.setText("Select Fasta File");
        jmiSelectFasta.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jmiSelectFastaActionPerformed(evt);
            }
        });
        jMenu1.add(jmiSelectFasta);

        jMenuSelectPlgs.setText("Select PLGS File");
        jMenuSelectPlgs.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jMenuSelectPlgsActionPerformed(evt);
            }
        });
        jMenu1.add(jMenuSelectPlgs);

        jMenuBar1.add(jMenu1);

        jMenu2.setText("Edit");
        jMenuBar1.add(jMenu2);

        setJMenuBar(jMenuBar1);

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
        getContentPane().setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addComponent(jPanel1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
            .addComponent(jPanel5, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
                .addComponent(jPanel5, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                .addComponent(jPanel1, javax.swing.GroupLayout.PREFERRED_SIZE, 462, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addGap(29, 29, 29))
        );

        java.awt.Dimension screenSize = java.awt.Toolkit.getDefaultToolkit().getScreenSize();
        setBounds((screenSize.width-675)/2, (screenSize.height-590)/2, 675, 590);
    }// </editor-fold>//GEN-END:initComponents

    private void jMenuSelectPlgsActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jMenuSelectPlgsActionPerformed

        JFileChooser fileChooser = new javax.swing.JFileChooser("user.home");
        fileChooser.setDialogTitle("Select a PLGS file");
        fileChooser.setCurrentDirectory(currentDirectory);

        //... Applying file extension filters ...//
        FileNameExtensionFilter filter = new FileNameExtensionFilter("XML (*.xml)", "xml");
        fileChooser.setFileFilter(filter);

        int returnVal = fileChooser.showOpenDialog(this);
        if (returnVal == JFileChooser.APPROVE_OPTION) {
            File file = fileChooser.getSelectedFile();
            this.jtfPlgsFile.setText(file.getAbsolutePath());
            currentDirectory = file.getParentFile();
        }
    }//GEN-LAST:event_jMenuSelectPlgsActionPerformed

    private void adFixedModActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_adFixedModActionPerformed

        Object[] selectedFixedMods = jListMods.getSelectedValues();
        ListModel fixedModsModel = jListFixedMods.getModel();

        int oldSize = fixedModsModel.getSize();
        Object[] oldFixedMods = new Object[oldSize];
        for (int i = 0; i < oldSize; i++) {
            oldFixedMods[i] = fixedModsModel.getElementAt(i);
        }

        //Object[] oldFixedMods = fixedModsModel.toArray();

        if (oldFixedMods[0].equals("--- none selected ---")) {
//            for (Object mod : selectedFixedMods){
//                fixedModsModel.addElement(mod);
//            }
            DefaultListModel listModel = new DefaultListModel();

            if (selectedFixedMods.length != 0) {
                for (Object mod : selectedFixedMods) {
                    listModel.addElement(mod);
                }
                jListFixedMods.setModel(listModel);
            }
        }
        else {
            DefaultListModel listModel = new DefaultListModel();
            Object[] allMods = ArrayUtils.addAll(oldFixedMods, selectedFixedMods);
            Arrays.sort(allMods);
//            for (Object mod : allMods){
//                fixedModsModel.addElement(mod);
//            }
            for (Object mod : allMods) {
                if (!listModel.contains(mod)) {
                    listModel.addElement(mod);
                }
            }
            jListFixedMods.setModel(listModel);
        }
    }//GEN-LAST:event_adFixedModActionPerformed

    private void adVarModActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_adVarModActionPerformed

        Object[] selectedVarMods = jListMods.getSelectedValues();
        ListModel varModsModel = jListVarMods.getModel();
        int oldSize = varModsModel.getSize();
        Object[] oldVarMods = new Object[oldSize];
        for (int i = 0; i < oldSize; i++) {
            oldVarMods[i] = varModsModel.getElementAt(i);
        }

        if (oldVarMods[0].equals("--- none selected ---")) {
            DefaultListModel listModel = new DefaultListModel();

            if (selectedVarMods.length != 0) {
                for (Object mod : selectedVarMods) {
                    listModel.addElement(mod);
                }
                jListVarMods.setModel(listModel);
            }
        }
        else {
            DefaultListModel listModel = new DefaultListModel();
            Object[] allMods = ArrayUtils.addAll(oldVarMods, selectedVarMods);
            Arrays.sort(allMods);
            for (Object mod : allMods) {
                if (!listModel.contains(mod)) {
                    listModel.addElement(mod);
                }
            }
            jListVarMods.setModel(listModel);
        }
    }//GEN-LAST:event_adVarModActionPerformed

    private void rmFixedModActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_rmFixedModActionPerformed

        Object[] selectedFixedMods = jListFixedMods.getSelectedValues();
        ListModel fixedModsModel = jListFixedMods.getModel();

        int size = fixedModsModel.getSize();
        Object[] fixedMods = new Object[size];
        for (int i = 0; i < size; i++) {
            fixedMods[i] = fixedModsModel.getElementAt(i);
        }

        List<Object> fixedModsList = new LinkedList(Arrays.asList(fixedMods));

        for (Object mod : selectedFixedMods) {
            fixedModsList.remove(mod);
        }

        if (fixedModsList.isEmpty()) {
            fixedModsList.add("--- none selected ---");
        }

        DefaultListModel newFixedModsModel = new DefaultListModel();

        for (Object mod : fixedModsList) {
            newFixedModsModel.addElement(mod);
        }

        jListFixedMods.setModel(newFixedModsModel);

    }//GEN-LAST:event_rmFixedModActionPerformed

    private void rmVarModActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_rmVarModActionPerformed

        Object[] selectedVarMods = jListVarMods.getSelectedValues();
        ListModel varModsModel = jListVarMods.getModel();

        int size = varModsModel.getSize();
        Object[] varMods = new Object[size];
        for (int i = 0; i < size; i++) {
            varMods[i] = varModsModel.getElementAt(i);
        }

        List<Object> varModsList = new LinkedList(Arrays.asList(varMods));

        for (Object mod : selectedVarMods) {
            varModsList.remove(mod);
        }

        if (varModsList.isEmpty()) {
            varModsList.add("--- none selected ---");
        }

        DefaultListModel newVarModsModel = new DefaultListModel();

        for (Object mod : varModsList) {
            newVarModsModel.addElement(mod);
        }

        jListVarMods.setModel(newVarModsModel);
    }//GEN-LAST:event_rmVarModActionPerformed

    private void jmiSelectFastaActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jmiSelectFastaActionPerformed

        JFileChooser fileChooser = new javax.swing.JFileChooser("user.home");
        fileChooser.setDialogTitle("Select a Fasta file");
        fileChooser.setCurrentDirectory(currentDirectory);

        //... Applying file extension filters ...//
        FileNameExtensionFilter filter = new FileNameExtensionFilter("FASTA (*.fasta)", "fasta");
        fileChooser.setFileFilter(filter);

        int returnVal = fileChooser.showOpenDialog(this);
        if (returnVal == JFileChooser.APPROVE_OPTION) {
            File file = fileChooser.getSelectedFile();
            this.jtfFastaFile.setText(file.getAbsolutePath());
            currentDirectory = file.getParentFile();
        }
    }//GEN-LAST:event_jmiSelectFastaActionPerformed

    private void jbRunActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jbRunActionPerformed

        //check if plgs file is selected
        if (jtfFastaFile.getText().isEmpty() && jtfPlgsFile.getText().isEmpty()) {
            JOptionPane.showMessageDialog(this.jPanel5, "Please select a fasta file and a plgsfile!", "File missing", JOptionPane.INFORMATION_MESSAGE);
        }
        else if (jtfPlgsFile.getText().isEmpty() && !jtfFastaFile.getText().isEmpty()) {
            JOptionPane.showMessageDialog(this.jPanel5, "Please select a plgs file!", "File missing", JOptionPane.INFORMATION_MESSAGE);
        }
        else if (!jtfPlgsFile.getText().isEmpty() && jtfFastaFile.getText().isEmpty()) {
            JOptionPane.showMessageDialog(this.jPanel5, "Please select a fasta file!", "File missing", JOptionPane.INFORMATION_MESSAGE);
        }
        else {
            /*
             * setting all the parameters
             */
            // set plgs file
            plgsFile = jtfPlgsFile.getText();

            // set fast file
            fastaFile = jtfFastaFile.getText();

            // set noCrosslinkOnCterminus
            noCrosslinksOnCterminus = jcbNoCrosslinksOnCterminus.isSelected();

            // set noCrosslinksOnModifiedResidues
            noCrosslinksOnModifiedResidues = jcbNoCrosslinksOnModifiedResidues.isSelected();

            // set crosslink mass shift
            xlMassShift = Double.valueOf(jspXlMassShift.getModel().getValue().toString());

            // set xlResidue
            xlResidue = jcbXlResidue.getModel().getSelectedItem().toString();

            // set missedCleaves
            missedCleaves = Integer.parseInt(jspMissedCleaves.getValue().toString());

            // set ppm tolerance
            ppmTol = Double.valueOf(jspPpmTol.getValue().toString());

            // set minimum peptide length used in calculation
            minPeptideLength = Integer.parseInt(jspMinPepLen.getValue().toString());

            // set fixed modification
            fixedMods = new HashMap();
            ListModel fixedModsModel = jListFixedMods.getModel();
            //// get all items in the fixed mods list
            int size = fixedModsModel.getSize();
            for (int i = 0; i < size; i++) {
                String modName = fixedModsModel.getElementAt(i).toString();
                ModificationElement modEl = ModificationElement.getModificationElement(modName);
                if (modEl != null && modEl != ModificationElement.NoSelecton) {
                    fixedMods.put(Integer.toString(i), modEl);
                }
            }

            //TODO: transfer fixedMods to HashMap<String, Double> to fit current CrosslinkAnalysis variable
            //TODO: in the future, change the fixedMods to HashMap<String, ModificationElement> in CrosslinkAnalysis
            fMods = new HashMap();
            for (String id : fixedMods.keySet()) {
                ModificationElement modEl = fixedMods.get(id);
                String[] residues = modEl.getModPositions();
                Double massShift = modEl.getMassShift();
                for (String residue : residues) {
                    fMods.put(residue, massShift);
                }
            }

            // set variable modification
            varMods = new HashMap();
            ListModel varModsModel = jListVarMods.getModel();
            //// get all items in the variable mods list
            size = varModsModel.getSize();
            for (int i = 0; i < size; i++) {
                String modName = varModsModel.getElementAt(i).toString();
                ModificationElement modEl = ModificationElement.getModificationElement(modName);
                if (modEl != null && modEl != ModificationElement.NoSelecton) {
                    varMods.put(Integer.toString(i), modEl);
                }
            }

            //TODO: transfer varMods to HashMap<String, Double> to fit current CrosslinkAnalysis variable
            //TODO: in the future, change the varMods to HashMap<String, ModificationElement> in CrosslinkAnalysis
            vMods = new HashMap();
            for (String id : varMods.keySet()) {
                ModificationElement modEl = varMods.get(id);
                String[] residues = modEl.getModPositions();
                Double massShift = modEl.getMassShift();
                for (String residue : residues) {
                    vMods.put(residue, massShift);
                }
            }

            // set temporary mgf file
            try {
                File mgf = File.createTempFile("temp", ".mgf");
                mgfFile = mgf.getAbsolutePath();
            }
            catch (IOException ex) {
                Logger.getLogger(MainView.class.getName()).log(Level.SEVERE, null, ex);
            }

            // set output file
            JFileChooser fileChooser = new JFileChooser("user.home");
            fileChooser.setDialogTitle("Save to ...");
            fileChooser.setCurrentDirectory(currentDirectory);

            //... Applying file extension filters ...//
            FileNameExtensionFilter filter = new FileNameExtensionFilter("CSV (Comma delimited)(*.csv)", "csv");
            fileChooser.setFileFilter(filter);

            int returnVal = fileChooser.showSaveDialog(this);
            if (returnVal == JFileChooser.APPROVE_OPTION) {
                File file = fileChooser.getSelectedFile();

                // name the output result file with csv suffix //
                outputFile = file.getAbsolutePath().endsWith("csv") ? file.getAbsolutePath() : file.getAbsolutePath() + ".csv";
            }

            setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
            progressBar.setIndeterminate(true);

            runStartTime = System.currentTimeMillis();
            sw = new SwingWorker() {

                @Override
                protected Object doInBackground()
                        throws Exception {

                    CrosslinkAnalysis xlAnal = new CrosslinkAnalysis(plgsFile,
                                                                     mgfFile,
                                                                     outputFile,
                                                                     xlMassShift,
                                                                     xlResidue,
                                                                     vMods,
                                                                     fMods,
                                                                     missedCleaves,
                                                                     ppmTol,
                                                                     fastaFile);

                    return null;
                }

                @Override
                protected void done() {
                    setCursor(null);
                    progressBar.setIndeterminate(false);
                    JOptionPane.showMessageDialog(jPanel1, "Finished.");
                }

            };
            sw.run();
            //JOptionPane.showMessageDialog(this.jPanel1, "Finished.");

        }
    }//GEN-LAST:event_jbRunActionPerformed

    /**
     * @param args the command line arguments
     */
    public static void main(String args[]) {
        /*
         * Set the Nimbus look and feel
         */
        //<editor-fold defaultstate="collapsed" desc=" Look and feel setting code (optional) ">
        /*
         * If Nimbus (introduced in Java SE 6) is not available, stay with the default look and feel.
         * For details see http://download.oracle.com/javase/tutorial/uiswing/lookandfeel/plaf.html
         */
        try {
            for (javax.swing.UIManager.LookAndFeelInfo info : javax.swing.UIManager.getInstalledLookAndFeels()) {
                if ("Nimbus".equals(info.getName())) {
                    javax.swing.UIManager.setLookAndFeel(info.getClassName());
                    break;
                }
            }
        }
        catch (ClassNotFoundException ex) {
            java.util.logging.Logger.getLogger(MainView.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        }
        catch (InstantiationException ex) {
            java.util.logging.Logger.getLogger(MainView.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        }
        catch (IllegalAccessException ex) {
            java.util.logging.Logger.getLogger(MainView.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        }
        catch (javax.swing.UnsupportedLookAndFeelException ex) {
            java.util.logging.Logger.getLogger(MainView.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        }
        //</editor-fold>

        /*
         * Create and display the form
         */
        javax.swing.SwingUtilities.invokeLater(new Runnable() {

            public void run() {
                new MainView().setVisible(true);
            }

        });
    }
    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JButton adFixedMod;
    private javax.swing.JButton adVarMod;
    private javax.swing.JButton jButton1;
    private javax.swing.JLabel jLabel1;
    private javax.swing.JLabel jLabel2;
    private javax.swing.JLabel jLabel3;
    private javax.swing.JLabel jLabel4;
    private javax.swing.JLabel jLabel5;
    private javax.swing.JLabel jLabel6;
    private javax.swing.JLabel jLabel7;
    private javax.swing.JLabel jLabel8;
    private javax.swing.JLabel jLabel9;
    private javax.swing.JList jListFixedMods;
    private javax.swing.JList jListMods;
    private javax.swing.JList jListVarMods;
    private javax.swing.JMenu jMenu1;
    private javax.swing.JMenu jMenu2;
    private javax.swing.JMenuBar jMenuBar1;
    private javax.swing.JMenuItem jMenuSelectPlgs;
    private javax.swing.JPanel jPanel1;
    private javax.swing.JPanel jPanel2;
    private javax.swing.JPanel jPanel3;
    private javax.swing.JPanel jPanel4;
    private javax.swing.JPanel jPanel5;
    private javax.swing.JPanel jPanel6;
    private javax.swing.JScrollPane jScrollPane2;
    private javax.swing.JScrollPane jScrollPane3;
    private javax.swing.JScrollPane jScrollPane4;
    private javax.swing.JButton jbRun;
    private javax.swing.JCheckBox jcbNoCrosslinksOnCterminus;
    private javax.swing.JCheckBox jcbNoCrosslinksOnModifiedResidues;
    private javax.swing.JComboBox jcbXlResidue;
    private javax.swing.JMenuItem jmiSelectFasta;
    private javax.swing.JSpinner jspMinPepLen;
    private javax.swing.JSpinner jspMissedCleaves;
    private javax.swing.JSpinner jspPpmTol;
    private javax.swing.JSpinner jspXlMassShift;
    private javax.swing.JTextField jtfFastaFile;
    private javax.swing.JTextField jtfPlgsFile;
    private javax.swing.JProgressBar progressBar;
    private javax.swing.JButton rmFixedMod;
    private javax.swing.JButton rmVarMod;
    // End of variables declaration//GEN-END:variables
}
